package com.tg.push;

import static android.content.Context.NOTIFICATION_SERVICE;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.text.TextUtils;

import com.tange.base.toolkit.PhoneUtils;
import com.tange.base.toolkit.ProcessUtils;
import com.tange.core.backend.service.request.Http;
import com.tg.appcommon.android.TGLog;
import com.tg.push.initialization.MessagePush;
import com.tg.push.initialization.PushingConfiguration;

import java.util.List;

/**
 * 推送初始化管理
 */
public class PushManager {

    public static final String TAG = MessagePush.TAG + "PushManager#";

    static BasePusher pusher;

    /** 若谷歌初始化失败过，那么回滚为阿里云推送 */
    private static boolean enableFcmPush = true;

    private static BasePusher huaweiPushImpl;

    /** 给外部的回调 */
    private static OnPushIdUpdateCallback onPushIdUpdateCallback;
    public static  final  String CHANNEL_ID_CALL ="bell_ring";

    /** 是否为谷歌渠道 */
    private static boolean googlePlayChannel = false;
    /** 是否集成了谷歌推送 */
    private static boolean integratedWithFcm = false;

    /**
     * 推送渠道选择
     *
     * 国内版和谷歌版，统一逻辑：
     *    优先判断 华为-vivo-oppo-小米推送 是否可用，可用的话，使用对应的厂商推送。
     *    若以上都不可用，那么
     *      若是：地区为海外+谷歌服务可用，使用谷歌推送
     *      否则：使用阿里云推送
     *
     * @param context
     */
    private static void init(Context context){

        // 仅主进程初始化推送（部分渠道在其他进程初始化会闪退！）
        final boolean isMainProcess = ProcessUtils.isMainProcess(context);
        if (!isMainProcess) {
            TGLog.i(TAG, "[init] ignore for non-main-process");
            return;
        }

        final String brand = Build.BRAND;

        TGLog.i(TAG, "[init] brand = " + brand);
        TGLog.i(TAG, "[init] huaweiPushImpl = " + huaweiPushImpl);

//        if (PhoneUtils.isHW() && PushUtils.isHuaweiEnable(context) && !googlePlayChannel) {
//            pusher = huaweiPushImpl;
//        }else if (brand.equalsIgnoreCase("vivo") && PushUtils.isVivoEnable(context)){
//            pusher = new VivoPusher();
//        }else if (PhoneUtils.isOppo() && PushUtils.isOppoEnable(context)){
//            pusher = new OppoPusher();
//        }else if (PhoneUtils.isMi() && PushUtils.isMiEnable(context)){
//            pusher = new XiaoMiPusher();
//        }else {
//
//            TGLog.i(TAG, "[init] not match any brand");
//
//            final Locale locale = context.getResources().getConfiguration().locale;
//            boolean isOverSea = !locale.getCountry().equalsIgnoreCase("cn");
//
//            TGLog.i(TAG, "[init] locale = " + locale);
//            TGLog.i(TAG, "[init] isOverSea = " + isOverSea);
//
//            // 注意这个值不可靠，所以增加了兜底逻辑，见enableFcmPush字段
//            boolean available =  GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)==ConnectionResult.SUCCESS;
//
//            TGLog.i(TAG, "[init] isGooglePlayAvailable = " + available);
//            TGLog.i(TAG, "[init] BuildConfig.IS_FCM_ON = " + integratedWithFcm);
//            TGLog.i(TAG, "[init] BuildConfig.IS_GOOGLE_PLAY = " + googlePlayChannel);
//            TGLog.i(TAG, "[init] enableFcmPush = " + enableFcmPush);
//
//            if (enableFcmPush && available && integratedWithFcm && isOverSea && isMainProcess){
//                pusher = new FCMPusher();
//            }else {
//                pusher = new AliyunPusher();
//            }
//        }



        pusher = new AliyunPusher();
        TGLog.i(TAG, "[init] pusher = " + pusher);

        pusher.init(context);

//        boolean isOppo = pusher instanceof  OppoPusher && !HeytapPushManager.isSupportPush();
//        boolean isVivo  =  pusher instanceof  VivoPusher && !PushClient.getInstance(context).isSupport();
//
//        if (isOppo || isVivo){
//            pusher = new AliyunPusher();
//            pusher.init(context);
//        }

        TGLog.i(TAG, "[init] final pusher = " + pusher);
    }

    public static void setGooglePlayChannel(boolean googlePlayChannel) {
        PushManager.googlePlayChannel = googlePlayChannel;
    }

    public static void setIntegratedWithFcm(boolean integratedWithFcm) {
        PushManager.integratedWithFcm = integratedWithFcm;
    }

    public static void setHuaweiPushImpl(BasePusher huaweiPushImpl) {
      //  PushManager.huaweiPushImpl = huaweiPushImpl;
    }

    public static void setOnPushIdUpdateCallback(OnPushIdUpdateCallback callback) {
        onPushIdUpdateCallback = callback;
    }

    public static PushManagerService  managerService(){
        if (pusher!=null){
            return pusher;
        }
        return null;
    }

    public static void  resetPusher(Context context){
        TGLog.i(TAG, "[resetPusher] ");
        pusher = new AliyunPusher();
        if (pusher!=null){
            pusher.init(context);
        }
    }
    public static BasePusher  getPusher(){
        if (pusher != null){
            return pusher;
        }
        return null;
    }

    public interface OnPushIdUpdateCallback {
        void onUpdate(String pushid);
    }

    private static NotificationChannel createNotificationChannelInfo(Context context, String id, int channelResId, int descriptionResId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O&&!TextUtils.isEmpty(id)) {
            // 通知渠道的id
            // 用户可以看到的通知渠道的名字.
            CharSequence name = context.getResources().getString(channelResId);
            // 用户可以看到的通知渠道的描述
            String description = context.getResources().getString(descriptionResId);
            int importance = NotificationManager.IMPORTANCE_MAX;
            NotificationChannel mChannel = new NotificationChannel(id, name, importance);
            // 配置通知渠道的属性
            mChannel.setDescription(description);
            // 设置通知出现时的闪灯（如果 android 设备支持的话）
            mChannel.enableLights(true);
            mChannel.setLightColor(Color.RED);
            // 设置通知出现时的震动（如果 android 设备支持的话）
            mChannel.enableVibration(true);
            mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
            return mChannel;
        }
        return null;
    }



    private static void createNotificationChannel(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
            NotificationChannel defalutChannel = createNotificationChannelInfo(context, "1", R.string.notification_channel_user, R.string.notification_description_user);
            NotificationChannel eventChannel = createNotificationChannelInfo(context,  getChannelIdWithPhone(context,"iot","pre54"), R.string.notification_channel_event, R.string.notification_description_event);
            NotificationChannel serviceChannel = createNotificationChannelInfo(context, getChannelIdWithPhone(context,"service","pre72"), R.string.notification_channel_service, R.string.notification_description_service);
            NotificationChannel userChannel = createNotificationChannelInfo(context, getChannelIdWithPhone(context,"user","pre61"), R.string.notification_channel, R.string.notification_description);
            NotificationChannel systemChannel = createNotificationChannelInfo(context, getChannelIdCall(context), R.string.notification_channel_system_call, R.string.notification_description_system_call);

            try {
                mNotificationManager.createNotificationChannel(defalutChannel);
                mNotificationManager.createNotificationChannel(eventChannel);
                mNotificationManager.createNotificationChannel(serviceChannel);
                mNotificationManager.createNotificationChannel(userChannel);
                if (systemChannel!=null){
                    mNotificationManager.createNotificationChannel(systemChannel);
                }
            }catch (Exception e){
                TGLog.i(TAG, "[createNotificationChannel ] ... failer");
            }


        }
    }

    public static void initPush(Context applicationContext) {
        TGLog.i(TAG, "[initPush] ... ");
        createNotificationChannel(applicationContext);
        initPushChannel(applicationContext);
    }

    public static String getChannelIdCall(Context applicationContext){
        if (PhoneUtils.isHW()||PhoneUtils.isMi()){
            NotificationManager mNotificationManager = (NotificationManager) applicationContext.getSystemService(NOTIFICATION_SERVICE);
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                List<NotificationChannel> pushs = mNotificationManager.getNotificationChannels();
                for (NotificationChannel channel: pushs) {
                    TGLog.i(TAG,"NotificationChannel channel: "+channel.getId()+" name:"+channel.getName()+" "+channel.getDescription());
                    if (PhoneUtils.isHW()){
                        if (!TextUtils.isEmpty(channel.getId())&&channel.getId().startsWith("com.huawei.android.pushagent")){
                            return channel.getId();
                        }
                    }
                    if (PhoneUtils.isMi()){
                        if (!TextUtils.isEmpty(channel.getId())&&channel.getId().endsWith(CHANNEL_ID_CALL)){
                            return channel.getId();
                        }
                    }

                }
            }
            return null;
        }
        return getChannelId(applicationContext,CHANNEL_ID_CALL);

    }
    private static String getChannelIdWithPhone(Context context,String key,String defaultValue){
        if (PhoneUtils.isMi()){
            return getChannelId(context,PushUtils.getBundleValue(context,"push.channel.xiaomi."+key,defaultValue));
        }
        return   PushUtils.getBundleValue(context,"push.channel.default."+key,defaultValue);
    }
    private static String getChannelId(Context applicationContext,String channelID){
        if (PhoneUtils.isMi()){
            return String.format("mipush|%s|%s",applicationContext.getPackageName(),channelID);
        }
        return  channelID;
    }
    private static void initPushChannel(Context applicationContext) {
        TGLog.i(TAG, "[initPushChannel] ... ");

        init(applicationContext);

        PushManagerService pushManagerService = PushManager.managerService();

        TGLog.i(TAG, "[initPushChannel] pushManagerService = " + pushManagerService);

        if (pushManagerService!=null){
            pushManagerService.register(applicationContext, new TGCommonCallback() {
                @Override
                public void onSuccess(String response) {
                    TGLog.i(TAG, "[initPushChannel][onSuccess] response = " + response);
                    TGLog.i(TAG, "[initPushChannel][onSuccess] push channel = " + pushManagerService.getPushChannel());

                    String pushID = response;
                    TGLog.i(TAG, "[initPushChannel][onSuccess] push_id =  " + pushID + ", length = " + pushID.length());

                    if ((TextUtils.isEmpty(pushID) || pushID.length() < 64) && (PhoneUtils.isHW() && PushUtils.isHuaweiEnable(applicationContext) && !googlePlayChannel)) {
                        TGLog.i(TAG, "[initPushChannel][onSuccess] reset push for huawei");
                        PushManager.resetPusher(applicationContext);
                    } else {
                        TGLog.i(TAG, "[initPushChannel][onSuccess] notify update , onPushIdUpdateCallback = " + onPushIdUpdateCallback);
                        if (onPushIdUpdateCallback != null) {
                            onPushIdUpdateCallback.onUpdate(response);
                        }
                    }
                }

                @Override
                public void onFailed(String errorCode, String errorMessage) {
                    TGLog.i(TAG, "[initPushChannel][onFailed] errorCode =  " + errorCode);
                    TGLog.i(TAG, "[initPushChannel][onFailed] errorMessage =  " + errorMessage);
                    TGLog.i(TAG, "[initPushChannel][onFailed] current push channel =  " + PushManager.getPusher());
                    TGLog.i(TAG, "[initPushChannel][onFailed] notify update , onPushIdUpdateCallback = " + onPushIdUpdateCallback);
                    if (onPushIdUpdateCallback != null) {
                        onPushIdUpdateCallback.onUpdate(errorCode);
                    }

                    MessagePush.INSTANCE.notifyInitializationStatus(new PushingConfiguration(false, errorCode + ", " + errorMessage, "", ""));

                }
            });
        }
    }

    public static boolean isFcm(){
        return false;
    }


    public static void updatePushID(String id){
        PushManagerService pushManagerService = PushManager.managerService();
        String channel = pushManagerService == null? "" : pushManagerService.getPushChannel();
        TGLog.i(TAG, "[updatePushID] id = " + id);
        TGLog.i(TAG, "[updatePushID] channel = " + channel);

        // TODO: 后台发版本后再切
        Http.INSTANCE
                .build()
                .path("v2/push/id")
                .param("id", id)
                .param("channel", channel)
                .post(httpResponse -> {
                    TGLog.i(TAG, "[updatePushID] response = " + httpResponse);
                    if (httpResponse.isSuccess()) {
                        MessagePush.INSTANCE.notifyInitializationStatus(new PushingConfiguration(true, "", channel, id));
                    } else {
                        MessagePush.INSTANCE.notifyInitializationStatus(new PushingConfiguration(false, "Failed to submit " + channel + " # " + id + " to remote: "
                                + httpResponse.getCode() + ", " + httpResponse.getMessage(), channel, id));
                    }
                });
    }
}
